package org.inspiration.dudu.content.service.impl;

import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.inspiration.dudu.common.constant.RedisConstant;
import org.inspiration.dudu.common.util.FileUtil;
import org.inspiration.dudu.common.util.RedisUtil;
import org.inspiration.dudu.content.mapper.CommentMapper;
import org.inspiration.dudu.content.model.dto.CommentDTO;
import org.inspiration.dudu.content.model.entity.CommentEntity;
import org.inspiration.dudu.content.model.vo.CommentVO;
import org.inspiration.dudu.content.service.CommentService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class CommentServiceImpl implements CommentService {

    private final RedisUtil redisUtil;
    private final CommentMapper commentMapper;

    private final RabbitTemplate rabbitTemplate;

    @Value("${dudu.rabbitmq.exchanges.like-exchange.name}")
    private String likeExchangeName;

    @Value("${dudu.rabbitmq.exchanges.like-exchange.queues.comment-like-queue.routing-key}")
    private String commentLikeRoutingKey;


    /**
     * 创建评论
     * @param commentEntity 评论实体
     */
    @Override
    public void createComment(CommentEntity commentEntity) {
        commentMapper.createComment(commentEntity);
    }

    /**
     * 将评论实体转换为视图对象
     * @param commentEntity 评论实体
     * @return 评论视图对象
     */
    @Override
    public CommentVO transToVO(CommentEntity commentEntity) {
        CommentVO commentVO = new CommentVO();
        BeanUtils.copyProperties(commentEntity, commentVO);
        // 从文件中读取内容
        String content = FileUtil.readStringFromFile(commentEntity.getContentFilePath());
        commentVO.setContent(content);
        return commentVO;
    }

    /**
     * 根据父评论ID以升序获取评论
     * @param parentId 父评论ID
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @return 评论视图对象列表
     */
    @Override
    public List<CommentVO> getCommentsByParentIdOrderByASC(String parentId, Integer pageNum, Integer pageSize) {
        List<CommentEntity> comments = commentMapper.getCommentsByParentIdOrderByASC(parentId, (pageNum - 1) * pageSize, pageSize);
        List<CommentVO> res = new ArrayList<>();
        for (CommentEntity commentEntity : comments) {
            CommentVO commentVO = transToVO(commentEntity);
            res.add(commentVO);
        }
        return res;
    }

    /**
     * 根据父评论ID以降序获取评论
     * @param parentId 父评论ID
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @return 评论视图对象列表
     */
    @Override
    public List<CommentVO> getCommentsByParentIdOrderByDESC(String parentId, Integer pageNum, Integer pageSize) {
        List<CommentEntity> comments = commentMapper.getCommentsByParentIdOrderByDESC(parentId, (pageNum - 1) * pageSize, pageSize);
        List<CommentVO> res = new ArrayList<>();
        for (CommentEntity commentEntity : comments) {
            CommentVO commentVO = transToVO(commentEntity);
            res.add(commentVO);
        }
        return res;
    }

    /**
     * 增加评论的点赞数
     * @param contentId 内容ID
     */
    @Override
    public void increaseLikeCount(String contentId) {
        String key = RedisConstant.COMMENT_KEY_PREFIX + contentId;
        redisUtil.incrementHashFieldWithLua(key, "likeCount");

        // 异步更新数据库
        Map<String, Object> map = new HashMap<>();
        map.put("contentId", contentId);
        map.put("action", "like");
        rabbitTemplate.convertAndSend(likeExchangeName, commentLikeRoutingKey, map);
    }

    /**
     * 减少评论的点赞数
     * @param contentId 内容ID
     */
    @Override
    public void decreaseLikeCount(String contentId) {
        String key = RedisConstant.COMMENT_KEY_PREFIX + contentId;
        redisUtil.decrementHashFieldWithLua(key, "likeCount");

        // 异步更新数据库
        Map<String, Object> map = new HashMap<>();
        map.put("contentId", contentId);
        map.put("action", "unlike");
        rabbitTemplate.convertAndSend(likeExchangeName, commentLikeRoutingKey, map);
    }



    /**
     * 根据内容ID获取用户ID
     * @param contentId 内容ID
     * @return 用户ID
     */
    @Override
    public Long getUserIdByContentId(String contentId) {
        return getCommentByContentId(contentId).getUserId();
    }

    /**
     * 根据内容ID获取评论实体
     * @param contentId 内容ID
     * @return 评论实体
     */
    @Override
    public CommentEntity getCommentByContentId(String contentId) {
        return redisUtil.queryHashCache(
                RedisConstant.COMMENT_KEY_PREFIX,
                contentId,
                CommentEntity.class,
                commentMapper::getCommentByContentId,
                60L,
                TimeUnit.SECONDS
        );
    }

    /**
     * 将评论DTO转换为评论实体
     * @param commentDTO 评论DTO
     * @param contentFilePath 内容文件路径
     * @param uuid 评论ID
     * @return 评论实体
     */
    @Override
    public CommentEntity transToEntity(CommentDTO commentDTO, String contentFilePath, String uuid) {
        CommentEntity commentEntity = new CommentEntity();
        BeanUtils.copyProperties(commentDTO, commentEntity);
        commentEntity.setContentFilePath(contentFilePath);
        commentEntity.setId(uuid);
        return commentEntity;
    }

    /**
     * 增加评论的评论数
     * @param contentId 内容ID
     */
    @Override
    public void increaseCommentCount(String contentId) {
        commentMapper.increaseCommentCount(contentId);
        String key = RedisConstant.COMMENT_KEY_PREFIX + contentId;
        redisUtil.deleteKey(key);
    }



    /**
     * 将评论标记为已读
     */
    @Override
    public void markAsRead(CommentDTO commentDTO) {
        commentMapper.markAsRead(commentDTO);
    }

    @Override
    public List<CommentEntity> getReceiveCommentsByUserIdOrderByDESC(Long userId, Integer pageNum, Integer pageSize) {
        return commentMapper.getReceiveCommentsByUserIdOrderByDESC(userId, (pageNum - 1) * pageSize, pageSize);
    }


}
